cmake_minimum_required(VERSION 3.20)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
    project(serializer VERSION 0.1.0 LANGUAGES CXX)
endif()

include(GNUInstallDirs)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# 头文件库（header-only）采用 INTERFACE 目标，统一传播包含与标准要求
if(NOT TARGET serializer)
    add_library(serializer INTERFACE)
    target_compile_features(serializer INTERFACE cxx_std_17)
endif()
if(NOT TARGET serializer::serializer)
    add_library(serializer::serializer ALIAS serializer)
endif()
target_include_directories(serializer INTERFACE
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/serializer>
)

# 引入并链接 stlcompat，使其包含路径与使用需求按依赖传播
if(NOT TARGET stlcompat)
    add_subdirectory(contrib/stlcompat)
endif()
target_link_libraries(serializer INTERFACE stlcompat::stlcompat)

# 测试选项：默认开启，但若未找到 GTest 则自动跳过
option(SERIALIZER_BUILD_TESTS "Build serializer tests" OFF)
if(SERIALIZER_BUILD_TESTS)
    enable_testing()
    # 兼容 CONFIG 与常规查找；允许使用环境变量注入 CMAKE_PREFIX_PATH（与顶层策略一致）
    if(NOT DEFINED ENV{CMAKE_PREFIX_PATH})
        # 可按需覆盖为你的 GTest 安装路径
        set(ENV{CMAKE_PREFIX_PATH} "/home/one/app/googletest-1.17.0/lib/cmake")
    endif()
    find_package(GTest CONFIG QUIET)
    if(NOT GTest_FOUND)
        find_package(GTest QUIET)
    endif()
    if(GTest_FOUND)
        # 设置 GTest 目标
        set(_gtest_main_target "")
        if(TARGET GTest::gtest_main)
            set(_gtest_main_target GTest::gtest_main)
        elseif(TARGET GTest::Main)
            set(_gtest_main_target GTest::Main)
        elseif(TARGET gtest_main)
            set(_gtest_main_target gtest_main)
        endif()
        if(NOT _gtest_main_target)
            if(DEFINED GTEST_MAIN_LIBRARIES OR DEFINED GTEST_LIBRARIES)
                set(_gtest_main_target "${GTEST_MAIN_LIBRARIES} ${GTEST_LIBRARIES}")
            else()
                message(FATAL_ERROR "GTest 已找到但未导出可用目标或变量，请检查 GTest 安装。")
            endif()
        endif()

        function(add_serializer_test target_name source_relpath)
            add_executable(${target_name} ${source_relpath})
            set_target_properties(${target_name} PROPERTIES
                CXX_STANDARD 17
                CXX_STANDARD_REQUIRED ON
            )
            target_link_libraries(${target_name} PRIVATE serializer ${_gtest_main_target})
            target_include_directories(${target_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
            add_test(NAME ${target_name} COMMAND ${target_name})
            set_tests_properties(${target_name} PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
        endfunction()

        # CPO机制测试
        add_serializer_test(cpo_test tests/cpo_test.cpp)

        # CPO 优先级测试：验证 tag_invoke 优先级与成员 serialize 的回退路径
        add_serializer_test(cpo_priority_test tests/cpo_priority_test.cpp)

        # CPO 与 ADL 绑定健壮性测试：验证默认实现与 CPO 同域后 ADL 稳定
        add_serializer_test(cpo_adl_binding_test tests/cpo_adl_binding_test.cpp)

        # CPO ADL 自由函数正向测试：验证 ADL 路径选择与字节序选项传递
        add_serializer_test(cpo_adl_free_functions_test tests/cpo_adl_free_functions_test.cpp)

        # CPO ADL 自由函数负向测试：验证全局/无关命名空间自由函数不会被 ADL 拾取
        add_serializer_test(cpo_adl_free_functions_negative_test tests/cpo_adl_free_functions_negative_test.cpp)

        # CPO 流式接口协作测试：验证 streaming 风格 IO 的端到端
        add_serializer_test(cpo_streaming_test tests/cpo_streaming_test.cpp)
        
        # CPO 基础类型测试
        add_serializer_test(cpo_basic_types_test tests/cpo_basic_types_test.cpp)
        
        # CPO 顺序容器测试
        add_serializer_test(cpo_containers_test tests/cpo_containers_test.cpp)
        
        # CPO 关联容器测试
        add_serializer_test(cpo_associative_containers_test tests/cpo_associative_containers_test.cpp)
        
        # CPO 复合类型测试
        add_serializer_test(cpo_composite_types_test tests/cpo_composite_types_test.cpp)
        
        # CPO 适配器容器测试
        add_serializer_test(cpo_adapter_containers_test tests/cpo_adapter_containers_test.cpp)
        
        # CPO 边界场景测试
        add_serializer_test(cpo_edge_cases_test tests/cpo_edge_cases_test.cpp)
        
        # CPO 现代容器测试：测试 string_view、span、valarray 等现代 C++ 容器
        add_serializer_test(cpo_modern_containers_test tests/cpo_modern_containers_test.cpp)
        
        # CPO 智能指针测试：测试 unique_ptr、shared_ptr 的序列化和反序列化
        add_serializer_test(cpo_smart_pointers_test tests/cpo_smart_pointers_test.cpp)
        
        # Simple IO 模块测试：测试 vector_writer 和 vector_reader 的功能
        add_serializer_test(io_test tests/io_test.cpp)
        
        # 概念模块测试：测试各种类型概念和约束
        add_serializer_test(concepts_test tests/concepts_test.cpp)
        
        # 容器特征模块测试：测试容器特征检测功能
        add_serializer_test(container_traits_test tests/container_traits_test.cpp)
        
        # 错误处理和异常安全测试：测试序列化库的健壮性
        add_serializer_test(error_handling_test tests/error_handling_test.cpp)
        
        # 性能和大数据测试：测试序列化库在各种负载下的表现
        add_serializer_test(performance_test tests/performance_test.cpp)
    else()
        message(STATUS "GTest 未找到，跳过 serializer 子库的测试构建")
    endif()
endif()

# 安装与导出：生成可供下游使用的包文件，并保持命名空间一致
install(DIRECTORY include/serializer DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(TARGETS serializer EXPORT SerializerTargets)
install(EXPORT SerializerTargets
    FILE serializerTargets.cmake
    NAMESPACE serializer::
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/serializer
)